/**
 * @brief any类的实现,用于保存请求的接收处理的上下文
 * @details 
 * 1.上下文需要可以保存任意类型的数据,而我们最开始又不知道是什么类型的数据,所以类型模板参数不能在any这里实现
 * 所以我们使用holder类里定义虚函数,placeholder类为模板类,继承自holder,any类中只包含holder类的指针
 */

#pragma once
#include <algorithm>

namespace hdp
{
    class Any
    {
    private:
        class holder
        {
        public:
            virtual ~holder() {}
            virtual const std::type_info &type() = 0;
            virtual holder *clone() = 0;
        };
        template <class T>
        class placeholder : public holder
        {
        public:
            placeholder(const T &val) : _val(val) {}
            // 获取子类对象保存的数据类型
            virtual const std::type_info &type() { return typeid(T); }
            // 针对当前的对象自身，克隆出一个新的子类对象
            virtual holder *clone() { return new placeholder(_val); }

        public:
            T _val;
        };

        holder *_content;

    public:
        Any() : _content(nullptr) {}
        template <class T>
        Any(const T &val) : _content(new placeholder<T>(val)) {}
        Any(const Any &other) : _content(other._content ? other._content->clone() : nullptr) {}
        ~Any() { delete _content; }

        Any &swap(Any &other)
        {
            std::swap(_content, other._content);
            return *this;
        }

        // 返回子类对象保存的数据的指针
        template <class T>
        T *get()
        {
            // 想要获取的数据类型，必须和保存的数据类型一致
            assert(typeid(T) == _content->type());
            return &((placeholder<T> *)_content)->_val;
        }
        // 赋值运算符的重载函数
        template <class T>
        Any &operator=(const T &val)
        {
            // 为val构造一个临时的通用容器，然后与当前容器自身进行指针交换，临时对象释放的时候，原先保存的数据也就被释放
            Any(val).swap(*this);
            return *this;
        }
        Any &operator=(const Any &other)
        {
            Any(other).swap(*this);
            return *this;
        }
    };
}